// 方法装饰器
// 参数一：如果是实例方法，为类的原型(对象类型)。如果是静态方法，为类本身(类构造函数类型)
// 参数二：字符串，表示方法名
// 参数三：属性描述对象，其实就是js的Object.defineProperty()中的属性描述对象{value:xxx,writable:xxx, enumerable:xxx, configurable:xxx}
/*
function d0(target:Record<string, any>, key: string) {
  console.log(target, key)
}

function d1(target:Record<string, any>, key: string, descriptor:PropertyDescriptor) {
  console.log(target, key, descriptor)
}

function d2(target:new (...args:any[])=>any, key: string, descriptor:PropertyDescriptor) {
  console.log(target, key, descriptor)
}

class A{
  @d0
  prop1: string;
  static prop2: string;

  @d1
  method1() { }

  @d2
  static method2() { }
}
*/

function enumerable() {
  return function (target:any, key: string, descriptor:PropertyDescriptor) {
    // console.log(target, key, descriptor)
    descriptor.enumerable = true;
  }
}

// 废弃方法装饰器
function noUse(str: string) {
  return function (target:any, key: string, descriptor:PropertyDescriptor) {
    descriptor.value = function () {
      console.log("该方法已经被废弃..." + str)
    }
  }
}

// 方法拦截装饰器
function interceptor(str: string) {
  return function (target:any, key: string, descriptor:PropertyDescriptor) {
    const temp = descriptor.value;
    descriptor.value = function (...args: any[]) {
      console.log("前置拦截---" + str);
      temp.call(this,...args);
      console.log("后置拦截---" + str);
    }
  }
}

class A{
  prop1: string = "aaa";
  prop2: string = "bbb";

  @enumerable()
  method1() { }

  @enumerable()
  @noUse("hello")
  method2() { 
    console.log("正常执行....")
    console.log("hello");
  }

  @enumerable()
  @interceptor("interceptor")
  method3(str: string) {
    console.log("正在执行method3---" + str);
  }
}

console.log("---- 打印对象属性和方法 ----")
const objA = new A();
// for (let prop in objA) {
//   console.log(prop);
// }

// objA.method2();

objA.method3("jack");